
/* -*- C++ -*- */

//=============================================================================
/*
* @author Feloweria <380374483@qq.com>
* Copyright (C) Feloweria
*
* $ID 2014-07-010 18:04:45 PM
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* @version 1.0
*/
//=============================================================================

#include <algorithm>
#include "Log/Log.h"
#include "Game/WorkThread.h"

FELOWRIA_BEGIN

TimeValue cur_time = 0;

WorkThread::WorkThread()
:id(0),loop_time(0.05)
{
	static int32 thread_id = 0;
	id = thread_id++;
	memset(recv_event_time,0,EVENT_QUEUE_NUM * sizeof(int32));
}

WorkThread::~WorkThread() 
{

}


bool WorkThread::Excute()
{
	TimeValue time = cur_time;

	std::vector<WorkThread*>::iterator tIter = thread_list.begin();
	for(std::vector<EventQueue>::iterator sIter = send_list.begin(), sIter_end = send_list.end();
		sIter != sIter_end;
		++tIter,++sIter)
	{
		if(!*tIter || sIter->size() == 0)
			continue;

		for(int i = 0;i < EVENT_QUEUE_NUM;++i)
		{
			if((*tIter)->recv_event_mutex[i].TryLock())
			{
				if((*tIter)->recv_event_queue[i].size() == 0)
					(*tIter)->recv_event_time[i] = cur_time;

				EventQueue &event_queue = (*tIter)->recv_event_queue[i];
				for_each(sIter->begin(),sIter->end(),[&tIter,&event_queue](Event &event)
				{
					if(event_queue.size() >= EVENT_QUEUE_SIZE)
						LOG_ERROR(String("Thread [") + StringConvertor<UTF8>::ToString((*tIter)->GetID()) + String("] event is full"));

					event_queue.push_back(event);
				});
				
				(*tIter)->recv_event_mutex[i].UnLock();
				sIter->clear();
				break;	
			}

			if(i == EVENT_QUEUE_NUM - 1)
				LOG_ERROR(String("Thread [") + StringConvertor<UTF8>::ToString((*tIter)->GetID()) + String("] all lock"));

		}
	}

	for(int i = 0; i < EVENT_QUEUE_NUM;++i)
	{
		if(recv_event_queue[i].size() > 0)
		{
			if(cur_time > recv_event_time[i] + 2)
			{
				recv_event_mutex[i].Lock();
				event_queue.swap(recv_event_queue[i]);
				recv_event_mutex[i].UnLock();
			}else if(recv_event_mutex[i].TryLock())
			{
				event_queue.swap(recv_event_queue[i]);
				recv_event_mutex[i].UnLock();
			}

			if(event_queue.size() > 0)
			{
				for_each(event_queue.begin(),event_queue.end(),[](Event &event){event();});
				event_queue.clear();
			}
		}
	}
	bool result = Update();

	if(cur_time - time > loop_time)
		printf("use %f\n", cur_time - time);
	else
		Wait(loop_time - (cur_time - time));
	
	
	return result;
}

FELOWRIA_END	
